from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
import random

# 图片路径列表
IMAGE_PATHS = [
    "resources/red.jpeg",
    "resources/orange.jpeg",
    "resources/yellow.jpeg",
    "resources/green.jpeg",
    "resources/blue.jpeg",
    "resources/purple.jpeg",
]

BACK_IMAGE_PATH = "resources/back.jpeg"
BACK_GROUND_IMAGE_PATH = "resources/background.jpeg"

class Tile(ButtonBehavior, Image):
    def __init__(self, image_path, **kwargs):
        super(Tile, self).__init__(**kwargs)
        self.image_path = image_path  # 卡片正面图片路径
        self.is_visible = False  # 标记卡片是否显示正面
        self.source = BACK_IMAGE_PATH  # 默认显示背面
        self.disabled = True  # 开始时禁用所有卡片
        self.fit_mode = "fill"  # 设置图像适应模式

    # 当卡片被点击时触发的方法
    def on_press(self):
        # 只有当卡片未被禁用且未显示正面时才响应点击
        if not self.disabled and not self.is_visible:
            self.parent.parent.on_tile_click(self)  # 触发父级布局的点击处理方法

    # 更新卡片显示的图片（正面或背面）
    def update_image(self):
        self.source = self.image_path if self.is_visible else BACK_IMAGE_PATH

class MatchGame(FloatLayout):  
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.cols = 8  # 网格列数
        self.rows = 8  # 网格行数
        self.tiles = []  # 存储Tile实例的列表
        self.previous_tile = None  # 上一次点击的卡片
        self.countdown_label = None  # 倒计时标签
        self.countdown_time = 5  # 修改倒计时时间以适应测试环境
        self.countdown_event = None  # 倒计时事件
        self.is_processing = False  # 标记是否正在处理卡片点击事件，防止重复点击

        # 设置窗口背景图片
        background = Image(source=BACK_GROUND_IMAGE_PATH, allow_stretch=True, keep_ratio=False)
        self.add_widget(background)  

        # 创建网格布局用于放置卡片
        self.board_layout = GridLayout(cols=self.cols, rows=self.rows, size_hint=(1, 1))
        self.add_widget(self.board_layout)

        # 初始化游戏板
        self.setup_board()

        # 设置倒计时标签
        self.setup_countdown_label()

        # 开始倒计时
        self.countdown_event = Clock.schedule_interval(self.update_countdown, 1)

    # 设置倒计时标签
    def setup_countdown_label(self):
        self.countdown_label = Label(
            text=f"Ready: {self.countdown_time} sec",
            font_size='96sp',  
            color=(1, 1, 0, 0.5),  
            bold=True,
            size_hint=(None, None),
            size=(400, 100),
            pos_hint={'center_x': 0.5, 'center_y': 0.5},
            halign='center',
            valign='middle'
        )
        self.add_widget(self.countdown_label)

    # 更新倒计时并处理倒计时结束后的操作
    def update_countdown(self, dt):
        self.countdown_time -= 1
        if self.countdown_time > 0:
            self.countdown_label.text = f"Ready: {self.countdown_time} sec"
        else:
            self.countdown_label.text = "Go!"
            self.hide_countdown()
            self.start_game()
            Clock.unschedule(self.countdown_event)  # 取消倒计时事件

    # 隐藏倒计时标签
    def hide_countdown(self):
        self.remove_widget(self.countdown_label)

    # 游戏开始，将所有卡片翻转为背面并允许点击
    def start_game(self):
        for tile in self.tiles:
            tile.is_visible = False
            tile.update_image()
            tile.disabled = False

    # 初始化游戏板，设置卡片
    def setup_board(self):
        total_tiles = self.cols * self.rows
        selected_images = {}

        while sum(selected_images.values()) < total_tiles:
            image_path = random.choice(IMAGE_PATHS)
            if image_path not in selected_images:
                selected_images[image_path] = 2
            elif selected_images[image_path] + 2 <= total_tiles and sum(selected_images.values()) + 2 <= total_tiles:
                selected_images[image_path] += 2

        IMAGE_PATHS_FOR_GAME = [path for path, count in selected_images.items() for _ in range(count)]
        random.shuffle(IMAGE_PATHS_FOR_GAME)

        for path in IMAGE_PATHS_FOR_GAME:
            tile = Tile(path)
            tile.is_visible = True  # 在倒计时期间显示正面
            tile.update_image()
            self.board_layout.add_widget(tile)
            self.tiles.append(tile)

    # 处理卡片点击事件
    def on_tile_click(self, tile):
        # 如果正在处理点击事件，则忽略新的点击
        if self.is_processing:
            return
            
        # 如果卡片已经显示正面或被禁用，则忽略点击
        if tile.is_visible or tile.disabled:
            return
            
        # 标记开始处理点击事件
        self.is_processing = True
        
        # 翻转卡片为正面
        tile.is_visible = True
        tile.update_image()

        # 如果这是第一次点击（没有上一张卡片）
        if self.previous_tile is None:
            self.previous_tile = tile  # 记录这张卡片为上一张卡片
        else:
            # 如果已经有上一张卡片，检查是否匹配
            if self.previous_tile.image_path == tile.image_path:
                # 如果匹配，移除两张卡片，并使用两个透明的卡片占位
                self.previous_tile.opacity = 0  # 设置上一张卡片为透明
                tile.opacity = 0  # 设置当前卡片为透明
                self.previous_tile.disabled = True  # 禁用上一张卡片，防止再次点击
                tile.disabled = True  # 禁用当前卡片，防止再次点击
                self.previous_tile = None  # 重置上一张卡片引用为空
            else:
                # 如果不匹配，则将上一张卡片翻回去，本次卡片不变
                self.flip_back(self.previous_tile)  # 将上一张卡片翻回去
                self.previous_tile = tile  # 将当前卡片设为下一次比较的基准

        # 处理完成，重置标记
        self.is_processing = False
                    
    # 翻回卡片到背面
    def flip_back(self, tile):
        tile.is_visible = False
        tile.update_image()

class MatchApp(App):
    def build(self):
        return MatchGame()

if __name__ == '__main__':
    MatchApp().run()
